package integral

import (
	"context"
	"encoding/json"
	"fmt"
	"private-domain-overseas-service/app/business/api/internal/repository/integral"
	"private-domain-overseas-service/pkg/common"
	"private-domain-overseas-service/pkg/status/bizintegral"
	"private-domain-overseas-service/pkg/xerr"
	"private-domain-overseas-service/tools/ent"
	"private-domain-overseas-service/tools/ent/hzintegralgoods"
	"private-domain-overseas-service/tools/ent/hzintegralwallet"
	"private-domain-overseas-service/tools/ent/predicate"
	"time"

	"private-domain-overseas-service/app/business/api/internal/svc"
	"private-domain-overseas-service/app/business/api/internal/types"

	"github.com/shopspring/decimal"

	"github.com/zeromicro/go-zero/core/logx"
)

type IntegralGoodsExchangeLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 兑换商品
func NewIntegralGoodsExchangeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IntegralGoodsExchangeLogic {
	return &IntegralGoodsExchangeLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *IntegralGoodsExchangeLogic) IntegralGoodsExchange(req *types.IntegralGoodsExchangeRequest) error {
	integralOrderDao := integral.NewIntegralOrderDao(l.ctx, l.svcCtx)
	integralWalletDao := integral.NewIntegralWalletDao(l.ctx, l.svcCtx)
	integralWalletRecordDao := integral.NewIntegralWalletRecordDao(l.ctx, l.svcCtx)
	integralGoodsDao := integral.NewIntegralGoodsDao(l.ctx, l.svcCtx)

	// 获取用户信息
	userId := common.JwtAuthUserId(l.ctx)

	// 查询商品信息
	integralGoodsInfo, err := integralGoodsDao.IntegralGoodsConditionsFirst(hzintegralgoods.IDEQ(int(req.GoodsId)))
	if err != nil {
		return xerr.ErrCodeMsg(xerr.ServerDataNotFoundError, fmt.Sprintf("查询商品失败：%v", err.Error()))
	}

	// 构建查询用户积分钱包条件
	walletCond := make([]predicate.HzIntegralWallet, 0)
	walletCond = append(walletCond, hzintegralwallet.UserIDEQ(userId))
	walletInfo, _ := integralWalletDao.IntegralWalletConditionsOnly(walletCond)

	// 处理商品价格
	amountFen := decimal.NewFromInt(integralGoodsInfo.GoodsPrice)
	if walletInfo.WalletActiveBalance < amountFen.IntPart() {
		return xerr.ErrCodeMsg(xerr.ServerApiIntegralNotEnoughError, "用户积分不足")
	}

	// 讲商品原始数据转换成json
	integralGoodsInfoJson, _ := json.Marshal(integralGoodsInfo)
	// 生成订单号
	orderNo := fmt.Sprintf("%s%d", "I", common.Snowflake())

	// 添加兑换订单
	err = common.WithTx(l.ctx, l.svcCtx.Orm, func(tx *ent.Tx) error {
		// 创建兑换订单
		integralOrderCreate := &ent.HzIntegralOrder{
			OrderGoodsID:           req.GoodsId,
			OrderUserID:            userId,
			OrderGoodsInfo:         integralGoodsInfo.GoodsInfo,
			OrderGoodsImage:        integralGoodsInfo.GoodsImage,
			OrderGoodsSmallImage:   integralGoodsInfo.GoodsSmallImage,
			OrderNo:                orderNo,
			OrderGoodsAmount:       integralGoodsInfo.GoodsPrice,
			OrderPayAmount:         amountFen.IntPart(),
			OrderStatus:            bizintegral.UnReceived,
			OrderOriginalGoodsInfo: string(integralGoodsInfoJson),
			CreatedAt:              time.Now().Unix(),
			UpdateAt:               time.Now().Unix(),
		}
		err = integralOrderDao.CreateIntegralOrder(integralOrderCreate, tx)
		if err != nil {
			return xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, "创建兑换商品订单失败")
		}

		// 钱包可用余额 - 商品积分价格
		walletInfo.WalletActiveBalance = walletInfo.WalletActiveBalance - amountFen.IntPart()
		// 更新用户积分钱包
		err = integralWalletDao.UpdateIntegralWallet(tx, walletInfo)
		if err != nil {
			return xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, "更新用户积分钱包失败")
		}

		// 添加积分变更记录
		integralWalletRecordCreate := &ent.HzIntegralWalletRecord{
			UserID:              userId,
			IntegralWalletID:    int64(walletInfo.ID),
			RecordTitle:         "兑换商品",
			RecordNumber:        fmt.Sprintf("%s%d", "IW", common.Snowflake()),
			RecordAmount:        amountFen.IntPart(),
			RecordStatus:        bizintegral.Disburse,
			RecordType:          bizintegral.DigitalCurrencyType,
			RecordActiveBalance: walletInfo.WalletActiveBalance,
			RecordFreezeBalance: walletInfo.WalletFreezeBalance,
		}
		err = integralWalletRecordDao.CreateIntegralWalletRecord(tx, integralWalletRecordCreate)
		if err != nil {
			return xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, "添加用户积分记录失败失败")
		}

		return nil
	})
	if err != nil {
		return xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, "创建订单失败")
	}

	return nil
}
